slimecing

a fighting game featuring slimes and swords
Log | Files | Refs | README

README.md (7355B)


      1 This sample shows how to set up a simple character controller using the input system. As there is more than one way to do it, the sample illustrates several ways. Each demonstration is set up as a separate scene. The basic functionality in all the scenes is the same. You can move and look around and fire projectiles (colored cubes) into the scene. In some scenes, only gamepads are supported but the more involved demonstrations support several different inputs concurrently.
      2 
      3 # SimpleDemo_UsingState
      4 
      5 [Source](./SimpleController_UsingState.cs)
      6 
      7 This starts off at the lowest level by demonstrating how to wire up input by polling input state directly in a `MonoBehaviour.Update` function. For simplicity's sake it only deals with gamepads but the same mechanism works in equivalent ways for other types of input devices (e.g. using `Mouse.current` and `Keyboard.current`).
      8 
      9 The key APIs demonstrated here are `Gamepad.current` and `InputControl.ReadValue`.
     10 
     11 ```CSharp
     12 public class SimpleController_UsingState : MonoBehaviour
     13 {
     14     //...
     15 
     16     public void Update()
     17     {
     18         var gamepad = Gamepad.current;
     19         if (gamepad == null)
     20             return;
     21 
     22         var move = Gamepad.leftStick.ReadValue();
     23         //...
     24     }
     25 }
     26 ```
     27 
     28 # SimpleDemo_UsingActions
     29 
     30 [Source](./SimpleController_UsingActions.cs)
     31 
     32 This moves one level higher and moves input over to "input actions". These are input abstractions that allow you to bind to input sources indirectly.
     33 
     34 In this scene, the actions are embedded directly into the character controller component. This allows setting up the bindings for the actions directly in the inspector. To see the actions and their bindings, select the `Player` object in the hierarchy and look at the `SimpleController_UsingActions` component in the inspector.
     35 
     36 The key APIs demonstrated here are `InputAction` and its `Enable`/`Disable` methods and its `ReadValue` method.
     37 
     38 ```CSharp
     39 public class SimpleController_UsingActions : MonoBehaviour
     40 {
     41     public InputAction moveAction;
     42     //...
     43 
     44     public void OnEnable()
     45     {
     46         moveAction.Enable();
     47         //...
     48     }
     49 
     50     public void OnDisable()
     51     {
     52         moveAction.Disable();
     53         //...
     54     }
     55 
     56     public void Update()
     57     {
     58         var move = moveAction.ReadValue<Vector2>();
     59         //...
     60     }
     61 }
     62 ```
     63 
     64 The sample also demonstrates how to use a `Tap` and a `SlowTap` interaction on the fire action to implement a charged shooting mechanism. Note that in this case, we run the firing logic right from within the action using the action's `started`, `performed`, and `canceled` callbacks.
     65 
     66 ```CSharp
     67         fireAction.performed +=
     68             ctx =>
     69         {
     70             if (ctx.interaction is SlowTapInteraction)
     71             {
     72                 StartCoroutine(BurstFire((int)(ctx.duration * burstSpeed)));
     73             }
     74             else
     75             {
     76                 Fire();
     77             }
     78             m_Charging = false;
     79         };
     80         fireAction.started +=
     81             ctx =>
     82         {
     83             if (ctx.interaction is SlowTapInteraction)
     84                 m_Charging = true;
     85         };
     86         fireAction.canceled +=
     87             ctx =>
     88         {
     89             m_Charging = false;
     90         };
     91 ```
     92 
     93 # SimpleDemo_UsingActionAsset
     94 
     95 [Source](./SimpleController_UsingActionAsset.cs)
     96 
     97 As more and more actions are added, it can become quite tedious to manually set up and `Enable` and `Disable` all the actions. We could use an `InputActionMap` in the component like so
     98 
     99 ```CSharp
    100 public class SimpleController : MonoBehaviour
    101 {
    102     public InputActionMap actions;
    103 
    104     public void OnEnable()
    105     {
    106         actions.Enable();
    107     }
    108 
    109     public void OnDisable()
    110     {
    111         actions.Disable();
    112     }
    113 }
    114 ```
    115 
    116 but then we would have to look up all the actions manually in the action map. A simpler approach is to put all our actions in a separate asset and generate a C# wrapper class that automatically performs the lookup for us.
    117 
    118 To create such an `.inputactions` asset, right-click in the Project Browser and click `Create >> Input Actions`. To edit the actions, double-click the `.inputactions` asset and a separate window will come up. The asset we use in this example is [SimpleControls.inputactions](SimpleControls.inputactions).
    119 
    120 When you select the asset, note that `Generate C# Class` is ticked in the import settings. This triggers the generation of [SimpleControls.cs](SimpleControls.cs) based on the `.inputactions` file.
    121 
    122 Regarding the `SimpleController_UsingActionAsset` script, there are some notable differences.
    123 
    124 ```CSharp
    125 public class SimpleController_UsingActionAsset
    126 {
    127     // This replaces the InputAction instances we had before with
    128     // the generated C# class.
    129     private SimpleControls m_Controls;
    130 
    131     //...
    132 
    133     public void Awake()
    134     {
    135         // To use the controls, we need to instantiate them.
    136         // This can be done arbitrary many times. E.g. there
    137         // can be multiple players each with its own SimpleControls
    138         // instance.
    139         m_Controls = new SimpleControls();
    140 
    141         // The generated C# class exposes all the action map
    142         // and actions in the asset by name. Here, we reference
    143         // the `fire` action in the `gameplay` action map, for
    144         // example.
    145         m_Controls.gameplay.fire.performed +=
    146         //...
    147     }
    148 
    149     //...
    150 
    151     public void Update()
    152     {
    153         // Same here, we can just look the actions up by name.
    154         var look = m_Controls.gameplay.look.ReadValue<Vector2>();
    155         var move = m_Controls.gameplay.move.ReadValue<Vector2>();
    156 
    157         //...
    158     }
    159 }
    160 ```
    161 
    162 Just for kicks, this sample also adds keyboard and mouse control to the game.
    163 
    164 # SimpleDemo_UsingPlayerInput
    165 
    166 [Source](./SimpleController_UsingPlayerInput.cs)
    167 
    168 Finally, we reached the highest level of the input system. While scripting input like in the examples above can be quick and easy, it becomes hard to manage when there can be multiple devices and/or multiple players in the game. This is where `PlayerInput` comes in.
    169 
    170 `PlayerInput` automatically manages per-player device assignments and can also automatically handle control scheme switching in single player (e.g. when the player switches between a gamepad and mouse&keyboard).
    171 
    172 In our case, we're not getting too much out of it since we don't have control schemes or multiple players but still, let's have a look.
    173 
    174 The first thing you'll probably notice is that now there are two script components on the `Player` object, one being the usual `SimpleController` and the other being `PlayerInput`. The latter is what now refers to [SimpleControls.inputactions](SimpleControls.inputactions). It also has `gameplay` set as the `Default Action Map` so that the gameplay actions will get enabled right away when `PlayerInput` itself is enabled.
    175 
    176 For getting callbacks, we have chosen `Invoke Unity Events` as the `Behavior`. If you expand the `Events` foldout in the inspector, you can see that `OnFire`, `OnMove`, and `OnLook` are added to the respective events. Each callback method here looks like the `started`, `performed`, and `canceled` callbacks we've already seen on `fireAction` before.
    177 
    178 ```CSharp
    179 public class SimpleController_UsingPlayerInput : MonoBehaviour
    180 {
    181     private Vector2 m_Move;
    182     //...
    183 
    184     public void OnMove(InputAction.CallbackContext context)
    185     {
    186         m_Move = context.ReadValue<Vector2>();
    187     }
    188 
    189     //...
    190 }
    191 ```